/**
 * Copyright 2019-2021 覃海林(qinhaisenlin@163.com).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */ 
package top.wardyan.common.config;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

//import org.slf4j.LoggerFactory;

import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.ext.handler.UrlSkipHandler;
import com.jfinal.ext.interceptor.SessionInViewInterceptor;
import com.jfinal.json.FastJsonFactory;
import com.jfinal.kit.Prop;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.jfinal.server.undertow.UndertowServer;
import com.jfinal.template.Engine;

import cn.hutool.cron.CronUtil;
import cn.hutool.log.Log;
import top.wardyan.base.common.config.ConfigProp;
import top.wardyan.base.common.handler.CommonHandler;
import top.wardyan.base.common.safe.XssHandler;
import top.wardyan.common.interceptor.RequestParamInterceptor;
import top.wardyan.wtask.jobs.FeishuSubscribe;

/**
 * 2021-09-05 改为final类,不再被继承. 增加启动检查:
 * @author harrydeep@wardyan.top
 */
public final class MainConfig extends JFinalConfig {
	
	
	// 开关: 要求授权  如果=false, 则不理会授权文件检查
	// public static final Boolean NEEDAUTHORIZED = true;
	// DEV版本:			不检查授权时间以及设备,用户数
	// UNLIMITED版本:	不检查授权时间,用户数
	// 但是公钥是必须要的
	


	// 使用 jfinal-undertow 时此处仅保留声明，不能有加载代码
	private static Prop p = ConfigProp.load();
	private List<DruidPlugin> dps = new ArrayList<>();			// 
	private List<ActiveRecordPlugin> arps = new ArrayList<>();
	
	// private static final org.slf4j.Logger log = LoggerFactory.getLogger(MainConfig.class);
	private static final Log log = Log.get();
	
	
	public static String VERSION = "";
	
	public static List<Integer> FUNCS = new ArrayList<>();
	public static List<String> CONFIGS = new ArrayList<>();
	
	public static String DEVICE = "";
	public static Integer SYSTEMID = 0;
	public static String SYSTEMNAME = "WStar";
	public static String ADDR = "";
	public static Integer PORT = 0;
	public static String DBNAME = "";
	public static String USER = "";
	public static String PASSWORD = "";
	public static Integer DBTYPE = 2;
	public static String DBTYPENAME = "MYSQL";
	public static Boolean ALLOWCONCURRENTLOGIN = false;
	public static Integer USERQTY = 0;
	public static String COPYRIGHT = "harrydeep@wardyan.top © 2020-2021";
	public static Integer INTERFACEOPTION = 0;	// 启用哪个接口
	public static Integer CLIENTID = 0;
	public static String CLIENTNAME = "";
	
	
	private static final String STARTINGCONFIG = "__starting__";
	public static Boolean DEBUG = false;		// 系统是否DEBUG DEBUG状态下会打印更多日志
	public static Boolean CHECKED = false;	// 是否已完成检查
	public static String HOST = "";
	
	
	public static final String CLIENT_STARTUP_PATH = "pub/api/client/startup";
	
	
	

	/**
	 *运行main方法启动项目
	 * 2021-12-03 增加:如果参数里有u,则为更新系统(从文件)
	 */
	public static void main(String[] args) {
		
		
		UndertowServer.start(MainConfig.class);
	}
	
	
	
	
	
	
	/**
	 * 配置JFinal常量
	 */
	@Override
	public void configConstant(Constants me) {	
		
		me.setJsonFactory(FastJsonFactory.me());
		//开启依赖注入
		me.setInjectDependency(true);
		// 开启超类注入
		me.setInjectSuperClass(true);
	}
	
	/**
	 * 配置JFinal路由映射
	 */
	@Override
	public void configRoute(Routes me) {
//		if(!go()) {
//			log.error("系统启动检查失败");
//			System.exit(-1);
//		}
//		me.scan("com.qinhailin");
		me.scan("top.wardyan");
		me.setMappingSuperClass(true);	// controller超类方法也映射
//		me.setBaseViewPath(WebContant.baseViewPath);
//		
//		// 如何配置是否启用这个接口, 以及定时任务?
//		if((INTERFACEOPTION & 1) > 0) {
//			log.warn("启用：数据检查工具接口");
//			me.add(new APIRoutes());
//		}
//		
//		if((INTERFACEOPTION & 2) > 0) {
//			log.warn("启用：统一API接口");
//			me.add(new ChecktoolAPIRoutes());
//		}
//		
		// me.add("", TestController.class);
		
		// System.out.println("1111");
	}
	
	/**
	 * 获取数据库插件
	 * 抽取成独立的方法，便于重用该方法，减少代码冗余
	 */
	public static DruidPlugin createDruidPlugin() {
		// 尝试加密
		// return new DruidPlugin(p.get("jdbcUrl"), p.get("user"), p.get("password").trim()).setFilters(p.get("dbconfig")).setPublicKey(p.get("publicKey"));
		// 改为在授权文件中
		String jdbcurl = String.format("jdbc:sqlserver://%s:%d; DatabaseName=%s; trustServerCertificate=true", "192.168.0.248", 1433, "ERPDB4");
		return new DruidPlugin(jdbcurl, "feng", "0400923");
	}
	
	/**
	 * 配置JFinal插件 数据库连接池 ORM 缓存等插件 自定义插件
	 */
	@Override
	public void configPlugin(Plugins me) {
		me.add(new EhCachePlugin());
		// ActiveRecordUtil.init("main", 1, "192.168.0.248", 1433, "ERPDB4", "feng", "0400923");
		top.wardyan.base.common.db.kits.ActiveRecordUtil.initAllDBConnectionFromConfig();
//		
//		// 配置数据库连接池插件
//		DruidPlugin dbPlugin = createDruidPlugin();		
//		/** 配置druid监控 **/
////		dbPlugin.addFilter(new StatFilter());
//		WallFilter wall = new WallFilter();
////		// wall.setDbType(p.get("dbType"));
//		wall.setDbType("sqlserver");
////		
////		// 配置
////		WallConfig wallConfig = wall.getConfig();
////		if(wallConfig == null) {
////			wallConfig = new WallConfig();
////		}
////		// 允许执行多语句
////		wallConfig.setMultiStatementAllow(p.getBoolean("MultiStatementAllow", false));
////		// 允许执行类似DECLARE这样的语句
////		wallConfig.setNoneBaseStatementAllow(p.getBoolean("NoneBaseStatementAllow", false));
////		wallConfig.setAlterTableAllow(p.getBoolean("AlterTableAllow",true));
////		wallConfig.setBlockAllow(p.getBoolean("BlockAllow",true));
////		wallConfig.setCallAllow(p.getBoolean("CallAllow",true));
////		wallConfig.setCaseConditionConstAllow(p.getBoolean("CaseConditionConstAllow",false));
////		wallConfig.setCommentAllow(p.getBoolean("CommentAllow",false));
////		wallConfig.setCommitAllow(p.getBoolean("CommitAllow",true));
////		wallConfig.setCompleteInsertValuesCheck(p.getBoolean("CompleteInsertValuesCheck",true));
////		wallConfig.setConditionAndAlwayFalseAllow(p.getBoolean("ConditionAndAlwayFalseAllow",false));
////		wallConfig.setConditionAndAlwayTrueAllow(p.getBoolean("ConditionAndAlwayTrueAllow",false));
////		wallConfig.setConditionDoubleConstAllow(p.getBoolean("ConditionDoubleConstAllow",false));
////		wallConfig.setConditionLikeTrueAllow(p.getBoolean("ConditionLikeTrueAllow",true));
////		wallConfig.setConditionOpBitwseAllow(p.getBoolean("ConditionOpBitwseAllow",true));
////		wallConfig.setConditionOpXorAllow(p.getBoolean("ConditionOpXorAllow",false));
////		wallConfig.setConstArithmeticAllow(p.getBoolean("ConstArithmeticAllow",true));
////		wallConfig.setCreateTableAllow(p.getBoolean("CreateTableAllow",true));
////		wallConfig.setConstArithmeticAllow(p.getBoolean("ConstArithmeticAllow",true));
////		wallConfig.setDeleteAllow(p.getBoolean("DeleteAllow",true));
////		wallConfig.setDeleteWhereAlwayTrueCheck(p.getBoolean("DeleteWhereAlwayTrueCheck",true));
////		wallConfig.setDescribeAllow(p.getBoolean("DescribeAllow",true));
////		wallConfig.setDeleteWhereNoneCheck(p.getBoolean("DeleteWhereNoneCheck",true));
////		wallConfig.setDoPrivilegedAllow(p.getBoolean("DoPrivilegedAllow",false));
////		wallConfig.setDropTableAllow(p.getBoolean("DropTableAllow",true));
////		wallConfig.setFunctionCheck(p.getBoolean("FunctionCheck",true));
////		wallConfig.setHintAllow(p.getBoolean("HintAllow",true));
////		wallConfig.setInsertAllow(p.getBoolean("InsertAllow",true));
////		// wallConfig.setInsertValuesCheckSize(p.getBoolean("",true));
////		wallConfig.setIntersectAllow(p.getBoolean("IntersectAllow",true));
////		wallConfig.setLimitZeroAllow(p.getBoolean("LimitZeroAllow",false));
////		wallConfig.setLockTableAllow(p.getBoolean("LockTableAllow",true));
////		wallConfig.setMergeAllow(p.getBoolean("MergeAllow",true));
////		wallConfig.setMetadataAllow(p.getBoolean("MetadataAllow",true));
////		wallConfig.setMinusAllow(p.getBoolean("MinusAllow",true));
////		wallConfig.setRenameTableAllow(p.getBoolean("RenameTableAllow",true));
////		wallConfig.setReplaceAllow(p.getBoolean("ReplaceAllow",true));
////		wallConfig.setRollbackAllow(p.getBoolean("RollbackAllow",true));
////		wallConfig.setSelectAllColumnAllow(p.getBoolean("SelectAllColumnAllow",true));
////		wallConfig.setSelectIntoAllow(p.getBoolean("SelectIntoAllow",true));
////		wallConfig.setSelelctAllow(p.getBoolean("SelelctAllow",true));
////		wallConfig.setSetAllow(p.getBoolean("SetAllow",true));
////		wallConfig.setShowAllow(p.getBoolean("ShowAllow",true));
////		wallConfig.setStartTransactionAllow(p.getBoolean("StartTransactionAllow",true));
////		wallConfig.setTruncateAllow(p.getBoolean("TruncateAllow",true));
////		wallConfig.setUpdateAllow(p.getBoolean("UpdateAllow",true));
////		wallConfig.setUseAllow(p.getBoolean("UseAllow",true));
//		dbPlugin.addFilter(wall);
//
//		// orm映射 配置ActiveRecord插件
//		ActiveRecordPlugin arp=new ActiveRecordPlugin("main", dbPlugin);
//		//sql模板
//		arp.getEngine().setSourceFactory(new ClassPathSourceFactory());
////		arp.addSqlTemplate(WebContant.sqlTemplate);
////		// 代码器模板
////		arp.addSqlTemplate(WebContant.codeTemplate);
//
//		//处理SQL参数	// 开发模式下才打印SQL
////		if(DEBUG) {
////			dbPlugin.addFilter(new MyDruidFilter());
////		}
//		// 任何时候都区分大小写
//		// arp.setContainerFactory(new CaseInsensitiveContainerFactory(false));
//		arp.setContainerFactory(new CaseInsensitiveContainerFactory());
//		
//		// 完全不支持oracle
////		if("sqlserver".equals(DBTYPENAME)){
////			// 配置属性名(字段名)大小写,true：小写，false:大写,统一小写，切换oracle数据库的时候可以不用改页面字段
////			arp.setDialect(new SqlServerDialect());			
////		}else {
////			arp.setDialect(new MysqlDialect());		
////		}
//		arp.setDialect(new SqlServerDialect());	
//		
//		/******** 在此添加数据库 表-Model 映射 *********/
//		// 只MAP声明为main主数据源的
////		TableScanner tableScanner=new TableScanner("com.qinhailin",arp, "main");
////		tableScanner.scan();
////		TableScanner tableScanner2=new TableScanner("top.wardyan",arp, "main");
////		tableScanner2.scan();
////		
////		_MappingKit.mapping(arp);
//		// 添加到插件列表中
//		me.add(dbPlugin);
//		me.add(arp);
//		
//		
//
//		// 扫描service
////		ServiceScanner serviceScanner = new ServiceScanner("com.qinhailin");
////		serviceScanner.scan();
////		ServiceScanner serviceScanner2 = new ServiceScanner("top.wardyan");
////		serviceScanner2.scan();
////		
//		
//		
//		
//		/******** 多数据源配置，接入第三方库进行登录或者业务开发 *********/
//		
////		// 配置缓存插件
////		me.add(new EhCachePlugin());
////		
////		// 配置定时任务 	//直接配置cron4j		// 直接配置5个任务
////		me.add(new Cron4jPlugin("task1.txt"));
////		me.add(new Cron4jPlugin("task2.txt"));
////		me.add(new Cron4jPlugin("task3.txt"));
////		me.add(new Cron4jPlugin("task4.txt"));
////		me.add(new Cron4jPlugin("task5.txt"));
//		
		
	}
	
	

	/**
	 * 配置全局拦截器
	 */
	@Override
	public void configInterceptor(Interceptors me) {
		me.addGlobalActionInterceptor(new SessionInViewInterceptor());
		me.addGlobalActionInterceptor(new RequestParamInterceptor());

	}
	
	/**
	 * 配置全局处理器
	 */
	@Override
	public void configHandler(Handlers me) {
		/** 配置druid监控 **/
		// 路由处理
		me.add(new CommonHandler());
		// XSS过滤
		me.add(new XssHandler("^\\/portal/form/view.*"));
		// 放开/ureport/开头的请求
		me.add(new UrlSkipHandler("^\\/ureport.*", true));
		
		//me.add(new UrlSkipHandler(".*/pub/rfid/*.*",false));
		
		//me.add(new UrlSkipHandler(".*/services.*",false));
		
		//me.add(new WebSocketHandler("^/websocket"));
		

	}
	
	/**
	 * 配置模板引擎
	 */
	@Override
	public void configEngine(Engine me) {

		me.setDevMode(true);
		
		Locale locale = new Locale("zh", "CN"); // 中文，中国
		Locale.setDefault(locale);
		
		Boolean enable = p.getBoolean("feishu.subscribe.enable", false);
		if(enable) {
			FeishuSubscribe.start();
		}
	}
	
	
	
	
	
	
	
	
	@Override
	public void onStart() {
		super.onStart();
		CronUtil.start();
	
		
	}

	@Override
	public void onStop() {
		CronUtil.stop();
		super.onStop();

	}

}	
